<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
    <title>Android应用程序窗口（Activity）的视图对象（View）的创建过程分析 - 老罗的Android之旅
        - 博客频道 - CSDN.NET</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="description" content="从前文可知道，每一个Activity组件都有一个关联的Window对象，用来描述一个应用程序窗口。每一个应用程序窗口内部又包含有一个View对象，用来描述应用程序窗口的视图。应用程序窗口视图是真正用来实现UI内容和布局的，也就是说，每一个Activity组件的UI内容和布局都是通过与其所关联的一个Window对象的内部的一个View对象来实现的。在本文中，我们就详细分析应用程序窗口视图的创建过程。" />
    <script src="http://static.blog.csdn.net/scripts/jquery.js" type="text/javascript"></script>
    <script type="text/javascript" src="http://static.blog.csdn.net/scripts/ad.js?v=1.1"></script>
        <!--new top-->
               <link rel="stylesheet" href="http://static.csdn.net/public/common/toolbar/css/index.css">        <!--new top-->

    <link rel="Stylesheet" type="text/css" href="http://static.blog.csdn.net/skin/default/css/style.css?v=1.1" />
    <link id="RSSLink" title="RSS" type="application/rss+xml" rel="alternate" href="/Luoshengyang/rss/list" />
    <link rel="shortcut icon" href="/favicon.ico" />
    <link type="text/css" rel="stylesheet" href="http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/default.css" />
 

</head>
<body>
    
   
      <!--new top-->
    <script id="toolbar-tpl-scriptId" fixed="true" prod="blog" skin="black" src="http://static.csdn.net/public/common/toolbar/js/html.js" type="text/javascript"></script>
     <!--new top-->
    <div id="container">
        <div id="header">
    <div class="header">
        <div id="blog_title">
            <h2>
                <a href="http://blog.csdn.net/luoshengyang">老罗的Android之旅</a></h2>
            <h3>爱生活，爱Android</h3>
            <div class="clear">
            </div>
        </div>
        <div class="clear">
        </div>
    </div>
</div>
<div id="navigator">
    <div class="navigator_bg">
    </div>
    <div class="navigator">
        <ul>
                <li id="btnContents"><a href="http://blog.csdn.net/luoshengyang?viewmode=contents"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_mulu'])">
                    <img src="http://static.blog.csdn.net/images/ico_list.gif">目录视图</span></a></li>
                <li id="btnView"><a href="http://blog.csdn.net/luoshengyang?viewmode=list"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_zhaiyao'])">
                    <img src="http://static.blog.csdn.net/images/ico_summary.gif">摘要视图</span></a></li>
                <li id="btnRss"><a href="http://blog.csdn.net/luoshengyang/rss/list"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_RSS'])">
                    <img src="http://static.blog.csdn.net/images/ico_rss.gif">订阅</span></a></li>
</ul>
    </div>
</div>
<script type="text/javascript">
    var username = "Luoshengyang";
    var _blogger = username;
    var blog_address = "http://blog.csdn.net/luoshengyang";
    var static_host = "http://static.blog.csdn.net";
    var currentUserName = "";
</script>

        <div id="body">
            <div id="main">
                <div class="main">
<div class="notice tracking-ad" data-mod='popu_3' > 


<a href="http://hero.csdn.net/Question/Details?ID=351&ExamID=346" target="_blank"><font color=blue>英雄会第四届在线编程大赛·线上初赛：带通配符的数
</font></a>

&nbsp;&nbsp;&nbsp;&nbsp;


<a href="http://bbs.csdn.net/topics/390724670"target="_blank">
<font color=red>CSDN社区“三八节”特别活动</font></a>
&nbsp;&nbsp;&nbsp;&nbsp;


<a href="http://www.csdn.net/article/2014-03-06/2818653"target="_blank">
<font color=blue>开发者职业生涯调查之未来</font></a>




</div>                    <link href="http://static.blog.csdn.net/css/comment1.css" type="text/css" rel="stylesheet" />
<link href="http://static.blog.csdn.net/css/style1.css" type="text/css" rel="stylesheet" />
<div id="article_details" class="details">
    <div class="article_title">
    <span class="ico ico_type_Original"></span>
    <h1>
        <span class="link_title"><a href="/luoshengyang/article/details/8245546">
        Android应用程序窗口（Activity）的视图对象（View）的创建过程分析
        </a></span>
    </h1>
</div>

    <div class="article_manage">
        <span class="link_categories">
        分类：
            <a href="/Luoshengyang/article/category/838604">Android</a> 
        </span>
    <span class="link_postdate">2012-12-10 00:55</span>
    <span class="link_view" title="阅读次数">22463人阅读</span>
    <span class="link_comments" title="评论次数"><a href="#comments" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_pinglun'])">评论</a>(32)</span>
    <span class="link_collect"><a href="javascript:void(0);" onclick="javascript:_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_shoucang']);collectArticle('Android应用程序窗口（Activity）的视图对象（View）的创建过程分析','8245546');return false;" title="收藏">收藏</a></span>
    <span class="link_report"><a href="#report"  onclick="javascript:_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_jubao']);report(8245546,2);return false;" title="举报">举报</a></span>
    
</div>
<div class="tag2box"><a href='http://www.csdn.net/tag/Activity' target=_blank onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">Activity</a><a href='http://www.csdn.net/tag/android' target=_blank onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">android</a><a href='http://www.csdn.net/tag/DecorView' target=_blank onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">DecorView</a><a href='http://www.csdn.net/tag/view' target=_blank onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">view</a><a href='http://www.csdn.net/tag/window' target=_blank onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">window</a></div>

    
<div id="article_content" class="article_content">
<p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; 从前文可知道，每一个</span><span style="color:black;">Activity</span><span style="color:black;">组件都有一个关联的</span><span style="color:black;">Window</span><span style="color:black;">对象，用来描述一个应用程序窗口。每一个应用程序窗口内部又包含有一个</span><span style="color:black;">View</span><span style="color:black;">对象，用来描述应用程序窗口的视图。应用程序窗口视图是真正用来实现</span><span style="color:black;">UI</span><span style="color:black;">内容和布局的，也就是说，每一个</span><span style="color:black;">Activity</span><span style="color:black;">组件的</span><span style="color:black;">UI</span><span style="color:black;">内容和布局都是通过与其所关联的一个</span><span style="color:black;">Window</span><span style="color:black;">对象的内部的一个</span><span style="color:black;">View</span><span style="color:black;">对象来实现的。在本文中，我们就详细分析应用程序窗口视图的创建过程。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; 在前面<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/8170307">Android应用程序窗口（Activity）实现框架简要介绍和学习计划</a>一文中提到，应用程序窗口内部所包含的视图对象的实际类型为DecorView。DecorView类继承了View类，是作为容器（ViewGroup）来使用的，它的实现如图1所示：</span></p><p style="text-align: center;"><span style="color: black; "><img src="http://img.my.csdn.net/uploads/201211/13/1352736693_6736.jpg" alt="" /><br /></span></p><p style="text-align: center;">图1 DecorView类的实现</p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个图的具体描述可以参考<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/8170307">Android应用程序窗口（Activity）实现框架简要介绍和学习计划</a>一文中的图5，这里不再详述。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;从前面<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/8170307">Android应用程序窗口（Activity）实现框架简要介绍和学习计划</a>一文还可以知道，每一个应用程序窗口的视图对象都有一个关联的ViewRoot对象，这些关联关系是由窗口管理器来维护的，如图2所示：</span></p><p style="text-align: center;"><span style="color: black; "><img width="684" src="http://img.my.csdn.net/uploads/201211/17/1353087703_2343.jpg" alt="" /><br /></span></p><p style="text-align: center;"><span style="color: black; ">图2 应用程序窗口视图与ViewRoot的关系图</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个图的具体描述可以参考<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/8170307">Android应用程序窗口（Activity）实现框架简要介绍和学习计划</a>一文中的图6，这里不再详述。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;简单来说，ViewRoot相当于是MVC模型中的Controller，它有以下职责：</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;1. 负责为应用程序窗口视图创建Surface。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;2. 配合WindowManagerService来管理系统的应用程序窗口。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;3. 负责管理、布局和渲染应用程序窗口视图的UI。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;那么，应用程序窗口的视图对象及其所关联的ViewRoot对象是什么时候开始创建的呢？ 从前面<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/8223770">Android应用程序窗口（Activity）的窗口对象（Window）的创建过程分析</a>一文可以知道，Activity组件在启动的时候，系统会为它创建窗口对象（Window），同时，系统也会为这个窗口对象创建视图对象。另一方面，当Activity组件被激活的时候，系统如果发现与它的应用程序窗口视图对象所关联的ViewRoot对象还没有创建，那么就会先创建这个ViewRoot对象，以便接下来可以将它的UI渲染出来。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; 从前面<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/6689748">Android应用程序启动过程源代码分析</a>一文可以知道，Activity组件在启动的过程中，会调用ActivityThread类的成员函数handleLaunchActivity，用来创建以及首次激活Activity组件，因此，接下来我们就从这个函数开始，具体分析应用程序窗口的视图对象及其所关联的ViewRoot对象的创建过程，如图3所示：</span></p><p style="text-align: center;"><span style="color:black;"><img width="680" src="http://img.my.csdn.net/uploads/201212/08/1354900406_7918.jpg" alt="" /><br /></span></p><p style="text-align: center;"><span style="color:black;">图3 应用程序窗口视图的创建过程</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个过程一共可以分为13个步骤，接下来我们就详细分析每一个步骤。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Step 1. ActivityThread.handleLaunchActivity</span></p><p><span style="color:black;"></span></p><pre code_snippet_id="129041" snippet_file_name="blog_20131226_1_157641"  code_snippet_id="129041" snippet_file_name="blog_20131226_1_157641" name="code" class="java">public final class ActivityThread {
    ......

    private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ......

        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            ......

            handleResumeActivity(r.token, false, r.isForward);

            ......
        }

        ......
    }

    ......
}</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个函数定义在文件frameworks/base/core/java/android/app/ActivityThread.java文件中。<br /><p></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;函数首先调用ActivityThread类的成员函数performLaunchActivity来创建要启动的Activity组件。在创建Activity组件的过程中，还会为该Activity组件创建窗口对象和视图对象。Activity组件创建完成之后，就可以将它激活起来了，这是通过调用ActivityThread类的成员函数handleResumeActivity来执行的。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;接下来，我们首先分析ActivityThread类的成员函数performLaunchActivity的实现，以便可以了解应用程序窗口视图对象的创建过程，接着再回过头来继续分析ActivityThread类的成员函数handleResumeActivity的实现，以便可以了解与应用程序窗口视图对象所关联的ViewRoot对象的创建过程。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Step 2.&nbsp;ActivityThread.performLaunchActivity</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个函数定义在文件frameworks/base/core/java/android/app/ActivityThread.java文件中。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这一步可以参考<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/8201936">Android应用程序窗口（Activity）的运行上下文环境（Context）的创建过程分析</a>一文的Step 1，它主要就是创建一个Activity组件实例，并且调用这个Activity组件实例的成员函数onCreate来让其执行一些自定义的初始化工作。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Step 3.&nbsp;Activity.onCreate</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个函数定义在文件frameworks/base/core/java/android/app/Activity.java中。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这一步可以参考<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/8201936">Android应用程序窗口（Activity）的运行上下文环境（Context）的创建过程分析</a>一文的Step 10。我们在实现一个Activity组件的时候，也就是在实现一个Activity子类的时候，一般都会重写成员函数onCreate，以便可以执行一些自定义的初始化工作，其中就包含初始化UI的工作。例如，在前面<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/6580267">在Ubuntu上为Android系统内置Java应用程序测试Application Frameworks层的硬件服务</a>一文中，我们实现了一个名称为Hello的Activity组件，用来测试硬件服务，它的成员函数onCreate的样子长得大概如下所示：</span></p><p><span style="color:black;"></span></p><pre code_snippet_id="129041" snippet_file_name="blog_20131226_2_4236842"  code_snippet_id="129041" snippet_file_name="blog_20131226_2_4236842" name="code" class="java">public class Hello extends Activity implements OnClickListener {  
    ......  
      
    /** Called when the activity is first created. */  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
  
        ......  
    }  

    ......
}</pre>&nbsp;&nbsp; &nbsp; &nbsp; 其中，调用从父类Activity继承下来的成员函数setContentView就是用来创建应用程序窗口视图对象的。<p></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; 接下来，我们就继续分析Activity类的成员函数setContentView的实现。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; Step 4.&nbsp;Activity.setContentView</span></p><p><span style="color:black;"></span></p><pre code_snippet_id="129041" snippet_file_name="blog_20131226_3_3855158"  code_snippet_id="129041" snippet_file_name="blog_20131226_3_3855158" name="code" class="java">public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks {
    ......

    private Window mWindow;
    ......

    public Window getWindow() {
        return mWindow;
    }
    ......

    public void setContentView(int layoutResID) {
        getWindow().setContentView(layoutResID);
    }

    ......
}</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个函数定义在文件frameworks/base/core/java/android/app/Activity.java中。<p></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Activity类的成员函数setContentView首先调用另外一个成员函数getWindow来获得成员变量mWindow所描述的一个窗口对象，接着再调用这个窗口对象的成员函数setContentView来执行创建应用程序窗口视图对象的工作。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;从前面<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/8223770">Android应用程序窗口（Activity）的窗口对象（Window）的创建过程分析</a>一文可以知道，Activity类的成员变量mWindow指向的是一个PhoneWindow对象，因此，接下来我们就继续分析PhoneWindow类的成员函数setContentView的实现。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Step 5. PhoneWindow.setContentView</span></p><p><span style="color:black;"></span></p><pre code_snippet_id="129041" snippet_file_name="blog_20131226_4_5948709"  code_snippet_id="129041" snippet_file_name="blog_20131226_4_5948709" name="code" class="java">public class PhoneWindow extends Window implements MenuBuilder.Callback {
    ......

    // This is the view in which the window contents are placed. It is either
    // mDecor itself, or a child of mDecor where the contents go.
    private ViewGroup mContentParent;
    ......

    @Override
    public void setContentView(int layoutResID) {
        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        mLayoutInflater.inflate(layoutResID, mContentParent);
        final Callback cb = getCallback();
        if (cb != null) {
            cb.onContentChanged();
        }
    }

    ......
}</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个函数定义在文件frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中。<p></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;PhoneWindow类的成员变量mContentParent用来描述一个类型为DecorView的视图对象，或者这个类型为DecorView的视图对象的一个子视图对象，用作UI容器。当它的值等于null的时候，就说明正在处理的应用程序窗口的视图对象还没有创建。在这种情况下，就会调用成员函数installDecor来创建应用程序窗口视图对象。否则的话，就说明是要重新设置应用程序窗口的视图。在重新设置之前，首先调用成员变量mContentParent所描述的一个ViewGroup对象来移除原来的UI内空。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;由于我们是在Activity组件启动的过程中创建应用程序窗口视图的，因此，我们就假设此时PhoneWindow类的成员变量mContentParent的值等于null。接下来，函数就会调用成员函数installDecor来创建应用程序窗口视图对象，接着再通过调用PhoneWindow类的成员变量mLayoutInflater所描述的一个LayoutInflater对象的成员函数inflate来将参数layoutResID所描述的一个UI布局设置到前面所创建的应用程序窗口视图中去，最后还会调用一个Callback接口的成员函数onContentChanged来通知对应的Activity组件，它的视图内容发生改变了。从前面<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/8223770">Android应用程序窗口（Activity）的窗口对象（Window）的创建过程分析</a>一文可以知道，Activity组件自己实现了这个Callback接口，并且将这个Callback接口设置到了与它所关联的应用程序窗口对象的内部去，因此，前面实际调用的是Activity类的成员函数onContentChanged来发出一个视图内容变化通知。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp;接下来，我们就继续分析PhoneWindow类的成员函数installDecor的实现，以便可以继续了解应用程序窗口视图对象的创建过程。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp;Step 6.&nbsp;PhoneWindow.installDecor</span></p><p><span style="color:black;"></span></p><pre code_snippet_id="129041" snippet_file_name="blog_20131226_5_3615178"  code_snippet_id="129041" snippet_file_name="blog_20131226_5_3615178" name="code" class="java">public class PhoneWindow extends Window implements MenuBuilder.Callback {
    ......

    // This is the top-level view of the window, containing the window decor.
    private DecorView mDecor;
    ......

    // This is the view in which the window contents are placed. It is either
    // mDecor itself, or a child of mDecor where the contents go.
    private ViewGroup mContentParent;
    ......

    private TextView mTitleView;
    ......

    private CharSequence mTitle = null;
    ......

    private void installDecor() {
        if (mDecor == null) {
            mDecor = generateDecor();
            ......
        }
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);

            mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
            if (mTitleView != null) {
                if ((getLocalFeatures() &amp; (1 &lt;&lt; FEATURE_NO_TITLE)) != 0) {
                    View titleContainer = findViewById(com.android.internal.R.id.title_container);
                    if (titleContainer != null) {
                        titleContainer.setVisibility(View.GONE);
                    } else {
                        mTitleView.setVisibility(View.GONE);
                    }
                    if (mContentParent instanceof FrameLayout) {
                        ((FrameLayout)mContentParent).setForeground(null);
                    }
                } else {
                    mTitleView.setText(mTitle);
                }
            }
        }
    }

    ......
}</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个函数定义在文件frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中。<p></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;由于我们是在Activity组件启动的过程中创建应用程序窗口视图的，因此，我们同时假设此时PhoneWindow类的成员变量mDecor的值等于null。这时候PhoneWindow类的成员函数installDecor就会调用另外一个成员函数generateDecor来创建一个DecorView对象，并且保存在PhoneWindow类的成员变量mDecor中。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;PhoneWindow类的成员函数installDecor接着再调用另外一个成员函数generateLayout来根据当前应用程序窗口的Feature来加载对应的窗口布局文件。这些布局文件保存在frameworks/base/core/res/res/layout目录下，它们必须包含有一个id值为“content”的布局控件。这个布局控件必须要从ViewGroup类继承下来，用来作为窗口的UI容器。PhoneWindow类的成员函数generateLayout执行完成之后，就会这个id值为“content”的ViewGroup控件来给PhoneWindow类的成员函数installDecor，后者再将其保存在成员变量mContentParent中。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; PhoneWindow类的成员函数installDecor还会检查前面加载的窗口布局文件是否包含有一个id值为“title”的TextView控件。如果包含有的话，就会将它保存在PhoneWindow类的成员变量mTitleView中，用来描述当前应用程序窗口的标题栏。但是，如果当前应用程序窗口是没有标题栏的，即它的Feature位FEATURE_NO_TITLE的值等于1，那么PhoneWindow类的成员函数installDecor就需要将前面得到的标题栏隐藏起来。注意，PhoneWindow类的成员变量mTitleView所描述的标题栏有可能是包含在一个id值为“title_container”的容器里面的，在这种情况下，就需要隐藏该标题栏容器。另一方面，如果当前应用程序窗口是设置有标题栏的，那么PhoneWindow类的成员函数installDecor就会设置它的标题栏文字。应用程序窗口的标题栏文字保存在PhoneWindow类的成员变量mTitle中，我们可以调用PhoneWindow类的成员函数setTitle来设置。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; 这一步执行完成之后，应用程序窗口视图就创建完成了，回到前面的Step 1中，即ActivityThread类的成员函数handleLaunchActivity中，接下来就会调用ActivityThread类的另外一个成员函数handleResumeActivity来激活正在启动的Activity组件。由于在是第一次激活该Activity组件，因此，在激活之前，还会为该Activity组件创建一个ViewRoot对象，并且与前面所创建的应用程序窗口视图关联起来，以便后面可以通过该ViewRoot对象来控制应用程序窗口视图的UI展现。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; 接下来，我们就继续分析ActivityThread类的成员函数handleResumeActivity的实现。</span></p><p><span style="color:black;">&nbsp;&nbsp; &nbsp; &nbsp; Step 7.&nbsp;ActivityThread.handleResumeActivity</span></p><p><span style="color:black;"></span></p><pre code_snippet_id="129041" snippet_file_name="blog_20131226_6_6265136"  code_snippet_id="129041" snippet_file_name="blog_20131226_6_6265136" name="code" class="java">public final class ActivityThread {
    ......

    final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
        ......

        ActivityClientRecord r = performResumeActivity(token, clearHide);

        if (r != null) {
            final Activity a = r.activity;
            ......

            // If the window hasn't yet been added to the window manager,
            // and this guy didn't finish itself or start another activity,
            // then go ahead and add the window.
            boolean willBeVisible = !a.mStartedActivity;
            if (!willBeVisible) {
                try {
                    willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
                            a.getActivityToken());
                } catch (RemoteException e) {
                }
            }
            if (r.window == null &amp;&amp; !a.mFinished &amp;&amp; willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                ......
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }
            } 

            ......
        }

        ......
    }
  
    ......
}</pre><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个函数定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ActivityThread类的成员函数handleResumeActivity首先调用另外一个成员函数performResumeActivity来通知Activity组件，它要被激活了，即会导致Activity组件的成员函数onResume被调用。ActivityThread类的成员函数performResumeActivity的返回值是一个ActivityClientRecord对象r，这个ActivityClientRecord对象的成员变量activity描述的就是正在激活的Activity组件a。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ActivityThread类的成员函数handleResumeActivity接下来判断正在激活的Activity组件接下来是否是可见的。如果是可见的，那么变量willBeVisible的值就会等于true。Activity类的成员变量mStartedActivity用来描述一个Activity组件是否正在启动一个新的Activity组件，并且等待这个新的Activity组件的执行结果。如果是的话，那么这个Activity组件的成员变量mStartedActivity的值就会等于true，表示在新的Activity组件的执行结果返回来之前，当前Activity组件要保持不可见的状态。因此，当Activity组件a的成员变量mStartedActivity的值等于true的时候，它接下来就是不可见的，否则的话，就是可见的。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;虽然说在Activity组件a的成员变量mStartedActivity的值等于true的情况下，它接下来的状态要保持不可见的，但是有可能它所启动的Activity组件的UI不是全屏的。在这种情况下，Activity组件a的UI仍然是有部分可见的，这时候也要将变量willBeVisible的值设置为true。因此，如果前面得到变量willBeVisible的值等于false，那么ActivityThread类的成员函数handleResumeActivity接下来就会通过Binder进程间通信机制来调用ActivityManagerService服务的成员函数willActivityBeVisible来检查位于Activity组件a上面的其它Activity组件（包含了Activity组件a正在等待其执行结果的Activity组件）是否是全屏的。如果不是，那么ActivityManagerService服务的成员函数willActivityBeVisible的返回值就会等于true，表示接下来需要显示Activity组件a。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 前面得到的ActivityClientRecord对象r的成员变量window用来描述当前正在激活的Activity组件a所关联的应用程序窗口对象。当它的值等于null的时候，就表示当前正在激活的Activity组件a所关联的应用程序窗口对象还没有关联一个ViewRoot对象。进一步地，如果这个正在激活的Activity组件a还活着，并且接下来是可见的，即ActivityClientRecord对象r的成员变量mFinished的值等于false，并且前面得到的变量willBeVisible的值等于true，那么这时候就说明需要为与Activity组件a所关联的一个应用程序窗口视图对象关联的一个ViewRoot对象。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 将一个Activity组件的应用程序窗口视图对象与一个ViewRoot对象关联是通过该Activity组件所使用的窗口管理器来执行的。从前面<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/8223770">Android应用程序窗口（Activity）的窗口对象（Window）的创建过程分析</a>一文可以知道，一个Activity组件所使用的本地窗口管理器保存它的成员变量mWindowManager中，这可以通过Activity类的成员函数getWindowManager来获得。在接下来的Step 10中，我们再分析Activity类的成员函数getWindowManager的实现。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 由于我们现在要给Activity组件a的应用程序窗口视图对象关联一个ViewRoot对象，因此，我们就需要首先获得这个应用程序窗口视图对象。从前面的Step 6可以知道，一个Activity组件的应用程序窗口视图对象保存在与其所关联的一个应用程序窗口对象的内部，因此，我们又要首先获得这个应用程序窗口对象。与一个Activity组件所关联的应用程序窗口对象可以通过调用该Activity组件的成员函数getWindow来获得。一旦获得了这个应用程序窗口对象（类型为PhoneWindow）之后，我们就可以调用它的成员函数getDecorView来获得它内部的视图对象。在接下来的Step 8和Step 9中，我们再分别分析Activity类的成员函数Activity类的成员函数getWindow和PhoneWindow类的成员函数getDecorView的实现。</p><p>&nbsp;&nbsp; &nbsp; &nbsp;在关联应用程序窗口视图对象和ViewRoot对象的时候，还需要第三个参数，即应用程序窗口的布局参数，这是一个类型为WindowManager.LayoutParams的对象，可以通过调用应用程序窗口的成员函数getAttributes来获得。一切准备就绪之后，还要判断最后一个条件是否成立，即当前正在激活的Activity组件a在本地进程中是否是可见的，即它的成员变量mVisibleFromClient的值是否等于true。如果是可见的，那么最后就可以调用前面所获得的一个本地窗口管理器wm（类型为LocalWindowManager）的成员函数addView来执行关联应用程序窗口视图对象和ViewRoot对象的操作。</p><p>&nbsp;&nbsp; &nbsp; 接下来，我们就分别分析Activity类的成员函数getWindow、PhoneWindow类的成员函数getDecorView、ctivity类的成员函数getWindowManager以及LocalWindowManager类的成员函数addView的实现。</p><p>&nbsp;&nbsp; &nbsp; Step 8.&nbsp;Activity.getWindow</p><p></p><pre code_snippet_id="129041" snippet_file_name="blog_20131226_7_1423350"  code_snippet_id="129041" snippet_file_name="blog_20131226_7_1423350" name="code" class="java">public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks {
    ......

    private Window mWindow;
    ......

    public Window getWindow() {
        return mWindow;
    }

    ......
}</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个函数定义在文件frameworks/base/core/java/android/app/Activity.java中。<p></p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;从前面<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/8223770">Android应用程序窗口（Activity）的窗口对象（Window）的创建过程分析</a>一文可以知道，Activity类的成员变量mWindow指向的是一个类型为PhoneWindow的窗口对象，因此，Activity类的成员函数getWindow返回给调用者的是一个PhoneWindow对象。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这一步执完成之后，返回到前面的Step 7中，即ActivityThread类的成员函数handleResumeActivity中，接下来就会继续调用前面所获得的一个PhoneWindow对象的成员函数getDecorView来获得当前正在激活的Activity组件所关联的一个应用程序窗口视图对象。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Step 9.&nbsp;PhoneWindow.getDecorView</p><p></p><pre code_snippet_id="129041" snippet_file_name="blog_20131226_8_9089818"  code_snippet_id="129041" snippet_file_name="blog_20131226_8_9089818" name="code" class="java">public class PhoneWindow extends Window implements MenuBuilder.Callback {
    ......

    private DecorView mDecor;
    ......

    @Override
    public final View getDecorView() {
        if (mDecor == null) {
            installDecor();
        }
        return mDecor;
    }

    ......
}</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个函数定义在文件frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中。<p></p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;PhoneWindow类的成员函数getDecorView首先判断成员变量mDecor的值是否等于null。如果是的话，那么就说明当前正在处理的应用程序窗口还没有创建视图对象。这时候就会调用另外一个成员函数installDecor来创建这个视图对象。从前面的调用过程可以知道，当前正在处理的应用程序窗口已经创建过视图对象，因此，这里的成员变量mDecor的值不等于null，PhoneWindow类的成员函数getDecorView直接将它返回给调用者。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这一步执完成之后，返回到前面的Step 7中，即ActivityThread类的成员函数handleResumeActivity中，接下来就会继续调用当前正在激活的Activity组件的成员函数getWindowManager来获得一个本地窗口管理器。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Step 10.&nbsp;Activity.getWindowManager</p><p></p><pre code_snippet_id="129041" snippet_file_name="blog_20131226_9_2819573"  code_snippet_id="129041" snippet_file_name="blog_20131226_9_2819573" name="code" class="java">public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks {
    ......

    private WindowManager mWindowManager;
    ......

    public WindowManager getWindowManager() {
        return mWindowManager;
    }

    ......
}</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个函数定义在文件frameworks/base/core/java/android/app/Activity.java中。<p></p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;从前面<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/8201936">Android应用程序窗口（Activity）的运行上下文环境（Context）的创建过程分析</a>一文可以知道，Activity类的成员变量mWindowManager指向的一是类型为LocalWindowManager的本地窗口管理器，Activity类的成员函数getWindowManager直接将它返回给调用者。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这一步执完成之后，返回到前面的Step 7中，即ActivityThread类的成员函数handleResumeActivity中，接下来就会继续调用前面所获得的一个LocalWindowManager对象的成员函数addView来为当前正在激活的Activity组件的应用程序窗口视图对象关联一个ViewRoot对象。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Step 11.&nbsp;LocalWindowManager.addView</p><p></p><pre code_snippet_id="129041" snippet_file_name="blog_20131226_10_8501174"  code_snippet_id="129041" snippet_file_name="blog_20131226_10_8501174" name="code" class="java">public abstract class Window {
    ......

    private class LocalWindowManager implements WindowManager {
        ......

        public final void addView(View view, ViewGroup.LayoutParams params) {
            ......

            mWindowManager.addView(view, params);
        }

        ......

        private final WindowManager mWindowManager;
 
        ......
    }

    ......
}</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个函数定义在文件frameworks/base/core/java/android/view/Window.java中。<p></p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;从前面<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/8223770">Android应用程序窗口（Activity）的窗口对象（Window）的创建过程分析</a>一文可以知道，LocalWindowManager类的成员变量mWindowManager指向的是一个WindowManagerImpl对象，因此，LocalWindowManager类的成员函数addView接下来调用WindowManagerImpl类的成员函数addView来给参数view所描述的一个应用程序窗口视图对象关联一个ViewRoot对象。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Step 12.&nbsp;WindowManagerImpl.addView</p><p></p><pre code_snippet_id="129041" snippet_file_name="blog_20131226_11_9755693"  code_snippet_id="129041" snippet_file_name="blog_20131226_11_9755693" name="code" class="java">public class WindowManagerImpl implements WindowManager {
    ......

    public void addView(View view, ViewGroup.LayoutParams params)
    {
        addView(view, params, false);
    }

    ......

    private void addView(View view, ViewGroup.LayoutParams params, boolean nest)
    {
        ......

        final WindowManager.LayoutParams wparams
                = (WindowManager.LayoutParams)params;

        ViewRoot root;
        View panelParentView = null;

        synchronized (this) {
            // Here's an odd/questionable case: if someone tries to add a
            // view multiple times, then we simply bump up a nesting count
            // and they need to remove the view the corresponding number of
            // times to have it actually removed from the window manager.
            // This is useful specifically for the notification manager,
            // which can continually add/remove the same view as a
            // notification gets updated.
            int index = findViewLocked(view, false);
            if (index &gt;= 0) {
                if (!nest) {
                    throw new IllegalStateException(&quot;View &quot; + view
                            + &quot; has already been added to the window manager.&quot;);
                }
                root = mRoots[index];
                root.mAddNesting++;
                // Update layout parameters.
                view.setLayoutParams(wparams);
                root.setLayoutParams(wparams, true);
                return;
            }

            // If this is a panel window, then find the window it is being
            // attached to for future reference.
            if (wparams.type &gt;= WindowManager.LayoutParams.FIRST_SUB_WINDOW &amp;&amp;
                    wparams.type &lt;= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
                final int count = mViews != null ? mViews.length : 0;
                for (int i=0; i&lt;count; i++) {
                    if (mRoots[i].mWindow.asBinder() == wparams.token) {
                        panelParentView = mViews[i];
                    }
                }
            }

            root = new ViewRoot(view.getContext());
            root.mAddNesting = 1;

            view.setLayoutParams(wparams);

            if (mViews == null) {
                index = 1;
                mViews = new View[1];
                mRoots = new ViewRoot[1];
                mParams = new WindowManager.LayoutParams[1];
            } else {
                index = mViews.length + 1;
                Object[] old = mViews;
                mViews = new View[index];
                System.arraycopy(old, 0, mViews, 0, index-1);
                old = mRoots;
                mRoots = new ViewRoot[index];
                System.arraycopy(old, 0, mRoots, 0, index-1);
                old = mParams;
                mParams = new WindowManager.LayoutParams[index];
                System.arraycopy(old, 0, mParams, 0, index-1);
            }
            index--;

            mViews[index] = view;
            mRoots[index] = root;
            mParams[index] = wparams;
        }
        // do this last because it fires off messages to start doing things
        root.setView(view, wparams, panelParentView);
    }

    ......

    private View[] mViews;
    private ViewRoot[] mRoots;
    private WindowManager.LayoutParams[] mParams;

    ......
}</pre><p>&nbsp;&nbsp; &nbsp; &nbsp; 这个函数定义在文件frameworks/base/core/java/android/view/WindowManagerImpl.java中。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 在WindowManagerImpl类中，两个参数版本的成员函数addView是通过调用三个参数版本的成同函数addView来实现的，因此，我们接下来就主要分析三个参数版本的成员函数addView的实现。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 在分析WindowManagerImpl类的三个参数版本的成员函数addView的实现之前，我们首先了解一下WindowManagerImpl类是如何关联一个应用程序窗口视图对象（View对象）和一个ViewRoot对象的。一个View对象在与一个ViewRoot对象关联的同时，还会关联一个WindowManager.LayoutParams对象，这个WindowManager.LayoutParams对象是用来描述应用程序窗口视图的布局属性的。</p><p>&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;WindowManagerImpl类有三个成员变量mViews、mRoots和mParams，它们分别是类型为View、ViewRoot和WindowManager.LayoutParams的数组。这三个数组的大小是始终保持相等的。这样， 有关联关系的View对象、ViewRoot对象和WindowManager.LayoutParams对象就会分别保存在数组mViews、mRoots和mParams的相同位置上，也就是说，mViews[i]、mRoots[i]和mParams[i]所描述的View对象、ViewRoot对象和WindowManager.LayoutParams对象是具有关联关系的。因此，WindowManagerImpl类的三个参数版本的成员函数addView在关联一个View对象、一个ViewRoot对象和一个WindowManager.LayoutParams对象的时候，只要分别将它们放在数组mViews、mRoots和mParams的相同位置上就可以了。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 理解了一个View对象、一个ViewRoot对象和一个WindowManager.LayoutParams对象是如何关联之后，WindowManagerImpl类的三个参数版本的成员函数addView的实现就容易理解了。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 参数view和参数params描述的就是要关联的View对象和WindowManager.LayoutParams对象。成员函数addView首先调用另外一个成员函数findViewLocked来检查参数view所描述的一个View对象是否已经存在于数组中mViews中了。如果已经存在的话，那么就说明该View对象已经关联过ViewRoot对象以及WindowManager.LayoutParams对象了。在这种情况下，如果参数nest的值等于false，那么成员函数addView是不允许重复对参数view所描述的一个View对象进行重新关联的。另一方面，如果参数nest的值等于true，那么成员函数addView只是重新修改参数view所描述的一个View对象及其所关联的一个ViewRoot对象内部使用的一个WindowManager.LayoutParams对象，即更新为参数params所描述的一个WindowManager.LayoutParams对象，这是通过调用它们的成员函数setLayoutParams来实现的。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 如果参数view所描述的一个View对象还没有被关联过一个ViewRoot对象，那么成员函数addView就会创建一个ViewRoot对象，并且将它与参数view和params分别描述的一个View对象和一个WindowManager.LayoutParams对象保存在数组mViews、mRoots和mParams的相同位置上。注意，如果数组mViews、mRoots和mParams尚未创建，那么成员函数addView就会首先分别为它们创建一个大小为1的数组，以便可以用来分别保存所要关联的View对象、ViewRoot对象和WindowManager.LayoutParams对象。另一方面，如果数组mViews、mRoots和mParams已经创建，那么成员函数addView就需要分别将它们的大小增加1，以便可以在它们的末尾位置上分别保存所要关联的View对象、ViewRoot对象和WindowManager.LayoutParams对象。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 还有另外一个需要注意的地方是当参数view描述的是一个子应用程序窗口的视图对象时，即WindowManager.LayoutParams对象wparams的成员变量type的值大于等于WindowManager.LayoutParams.FIRST_SUB_WINDOW并且小于等于WindowManager.LayoutParams.LAST_SUB_WINDOW时，那么成员函数addView还需要找到这个子视图对象的父视图对象panelParentView，这是通过遍历数组mRoots来查找的。首先，WindowManager.LayoutParams对象wparams的成员变量token指向了一个类型为W的Binder本地对象的一个IBinder接口，用来描述参数view所描述的一个子应用程序窗口视图对象所属的父应用程序窗口视图对象。其次，每一个ViewRoot对象都通过其成员变量mWindow来保存一个类型为W的Binder本地对象，因此，如果在数组mRoots中，存在一个ViewRoot对象，它的成员变量mWindow所描述的一个W对象的一个IBinder接口等于WindowManager.LayoutParams对象wparams的成员变量token所描述的一个IBinder接口时，那么就说明与该ViewRoot对象所关联的View对象即为参数view的父应用程序窗口视图对象。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;成员函数addView为参数view所描述的一个View对象和参数params所描述的一个WindowManager.LayoutParams对象关联好一个ViewRoot对象root之后，最后还会将这个View对view象和这个WindowManager.LayoutParams对象，以及变量panelParentView所描述的一个父应用程序窗视图对象，保存在这个ViewRoot对象root的内部去，这是通过调用这个ViewRoot对象root的成员函数setView来实现的，因此，接下来我们就继续分析ViewRoot类的成员函数setView的实现。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Step 13. ViewRoot.setView</p><p></p><pre code_snippet_id="129041" snippet_file_name="blog_20131226_12_9374009"  code_snippet_id="129041" snippet_file_name="blog_20131226_12_9374009" name="code" class="java">public final class ViewRoot extends Handler implements ViewParent,
        View.AttachInfo.Callbacks {
    ......

    final WindowManager.LayoutParams mWindowAttributes = new WindowManager.LayoutParams();
    ......

    View mView;
    ......

    final View.AttachInfo mAttachInfo;
    ......

    boolean mAdded;
    ......

    public void setView(View view, WindowManager.LayoutParams attrs,
            View panelParentView) {
        synchronized (this) {
            if (mView == null) {
                mView = view;
                mWindowAttributes.copyFrom(attrs);
                ......

                mAttachInfo.mRootView = view;
                .......

                if (panelParentView != null) {
                    mAttachInfo.mPanelParentWindowToken
                            = panelParentView.getApplicationWindowToken();
                }
                mAdded = true;
                ......

                requestLayout();
                ......
                try {
                    res = sWindowSession.add(mWindow, mWindowAttributes,
                            getHostVisibility(), mAttachInfo.mContentInsets,
                            mInputChannel);
                } catch (RemoteException e) {
                    mAdded = false;
                    mView = null;
                    ......
                    throw new RuntimeException(&quot;Adding window failed&quot;, e);
                } finally {
                    if (restore) {
                        attrs.restore();
                    }
                }

                ......
            }

            ......
        }
    }

    ......
}</pre><p></p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个函数定义在文件frameworks/base/core/java/android/view/ViewRoot.java中。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;参数view所描述的一个View对象会分别被保存在ViewRoot类的成员变量mView以及成员变量mAttachInfo所描述的一个AttachInfo的成员变量mRootView中，而参数attrs所描述的一个WindowManager.LayoutParams对象的内容会被拷贝到ViewRoot类的成员变量mWindowAttributes中去。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 当参数panelParentView的值不等于null的时候，就表示参数view描述的是一个子应用程序窗口视图对象。在这种情况下，参数panelParentView描述的就是一个父应用程序窗口视图对象。这时候我们就需要获得用来描述这个父应用程序窗口视图对象的一个类型为W的Binder本地对象的IBinder接口，以便可以保存在ViewRoot类的成员变量mAttachInfo所描述的一个AttachInfo的成员变量mPanelParentWindowToken中去。这样以后就可以知道ViewRoot类的成员变量mView所描述的一个子应用程序窗口视图所属的父应用程序窗口视图是什么了。注意，通过调用参数panelParentView的所描述的一个View对象的成员函数getApplicationWindowToken即可以获得一个对应的W对象的IBinder接口。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 上述操作执行完成之后，ViewRoot类的成员函数setView就可以将成员变量mAdded的值设置为true了，表示当前正在处理的一个ViewRoot对象已经关联好一个View对象了。接下来，ViewRoot类的成员函数setView还需要执行两个操作：</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 1. 调用ViewRoot类的另外一个成员函数requestLayout来请求对应用程序窗口视图的UI作第一次布局。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 2. 调用ViewRoot类的静态成员变量sWindowSession所描述的一个类型为Session的Binder代理对象的成员函数add来请求WindowManagerService增加一个WindowState对象，以便可以用来描述当前正在处理的一个ViewRoot所关联的一个应用程序窗口。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 至此，我们就分析完成Android应用程序窗口视图对象的创建过程了。在接下来的一篇文章中，我们将会继续分析Android应用程序窗口与WindowManagerService服务的连接过程，即Android应用程序窗口请求WindowManagerService为其增加一个WindowState对象的过程，而在接下来的两篇文章中，我们还会分析用来渲染Android应用程序窗口的Surface的创建过程，以及Android应用程序窗口的渲染过程。通过这三个过程的分析，我们就可以看到上述第1点和第2点提到的两个函数的执行过程，敬请期待！</p><p style="text-align: center;"><span style="color: rgb(204, 0, 0);"><strong><span style="font-size:14px;">老罗的新浪微博：<a target=_blank target="_blank" href="http://weibo.com/shengyangluo">http://weibo.com/shengyangluo</a>，欢迎关注！</span></strong></span><br /></p>
</div>



<!-- Baidu Button BEGIN -->
<div id="bdshare" class="bdshare_t bds_tools get-codes-bdshare" style="float: right;">
<a class="bds_qzone"></a>
<a class="bds_tsina"></a>
<a class="bds_tqq"></a>
<a class="bds_renren"></a>
<a class="bds_t163"></a>
<span class="bds_more">更多</span>
<a class="shareCount"></a>
</div>
<!-- Baidu Button END -->


<!--192.168.100.34-->
<div class="article_next_prev">
            <li class="prev_article"><span>上一篇：</span><a href="/luoshengyang/article/details/8223770" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_shangyipian'])">Android应用程序窗口（Activity）的窗口对象（Window）的创建过程分析</a></li>
            <li class="next_article"><span>下一篇：</span><a href="/luoshengyang/article/details/8275938" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_xiayipian'])">Android应用程序窗口（Activity）与WindowManagerService服务的连接过程分析</a></li>
</div>

<!-- Baidu Button BEGIN -->
<script type="text/javascript" id="bdshare_js" data="type=tools&amp;uid=1536434" ></script>
<script type="text/javascript" id="bdshell_js"></script>
<script type="text/javascript">
    document.getElementById("bdshell_js").src = "http://bdimg.share.baidu.com/static/js/shell_v2.js?cdnversion=" + Math.ceil(new Date()/3600000)
</script>
<!-- Baidu Button END -->

        <div id="digg" ArticleId="8245546">
            <dl id="btnDigg" class="digg digg_disable">
                <dt onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_ding'])">顶</dt>
                <dd>17</dd>
            </dl>
            <dl id="btnBury" class="digg digg_disable">
                <dt onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_cai'])">踩</dt>
                <dd>1</dd>
            </dl>
        </div>
</div>
      <dl class="blog-associat-tag">
        <dt>相关主题推荐</dt>
        <dd>
                <a href="http://www.csdn.net/tag/android应用" target="_blank">android应用</a> 
                <a href="http://www.csdn.net/tag/对象" target="_blank">对象</a> 
                <a href="http://www.csdn.net/tag/新浪微博" target="_blank">新浪微博</a> 
                <a href="http://www.csdn.net/tag/application" target="_blank">application</a> 
                <a href="http://www.csdn.net/tag/源代码" target="_blank">源代码</a> 
        </dd>
    </dl> 
    <dl class="blog-ass-articl">
        <dt>相关博文推荐</dt>
            <dd>
                <a href="http://blog.csdn.net/u010779363/article/details/21187837" title="打开chm文件的方法" target="_blank">打开chm文件的方法</a></dd>
            <dd>
                <a href="http://blog.csdn.net/perfect8886/article/details/21186623" title="LeetCode | Valid Number" target="_blank">LeetCode | Valid Num...</a></dd>
            <dd>
                <a href="http://blog.csdn.net/shi_weihappy/article/details/21184537" title="Cocos2dx游戏源码合集（BY懒骨头+持续更新+2014.02.21）" target="_blank">Cocos2dx游戏源码合集（BY懒骨头...</a></dd>
            <dd>
                <a href="http://blog.csdn.net/wty19/article/details/21178957" title="[学习] 数据挖掘-贝叶斯分类(例子，代码)" target="_blank">[学习] 数据挖掘-贝叶斯分类(例子，代...</a></dd>
            <dd>
                <a href="http://blog.csdn.net/u013936564/article/details/21180459" title="Enea保护数据库服务器与客户端应用程序之间的通信" target="_blank">Enea保护数据库服务器与客户端应用程序...</a></dd>
            <dd>
                <a href="http://blog.csdn.net/huiyang123/article/details/21177009" title="提交时提示错误This Bundle is invalid.New apps and app updates submitted to the App Store must be built with" target="_blank">提交时提示错误This Bundle i...</a></dd>
            <dd>
                <a href="http://blog.csdn.net/ChuiGeDaQiQiu/article/details/21175783" title="LRU-K缓存替换算法" target="_blank">LRU-K缓存替换算法</a></dd>
            <dd>
                <a href="http://blog.csdn.net/zouqingfang/article/details/21173575" title="基于Html5的兼容所有主流浏览器的在线视频播放器videoJs" target="_blank">基于Html5的兼容所有主流浏览器的在线...</a></dd>
    </dl>

    <div id="ad_cen">
        <script type="text/javascript">            BAIDU_CLB_SLOT_ID = "117306";</script>
        <script type="text/javascript" src="http://cbjs.baidu.com/js/o.js"></script>
    </div>
    <script type="text/javascript">
        //new Ad(4, 'ad_cen');
    </script>
<div id="comment_title" class="panel_head">
    查看评论<a name="comments"></a></div>
<div id="comment_list">
</div>
<div id="comment_bar">
</div>
<div id="comment_form">
</div>
<div class="announce">
    * 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场<a name="reply"></a><a name="quote"></a></div>
<script type="text/javascript">
    var fileName = '8245546';
    var commentscount = 32;
    var islock = false
</script>
<script type="text/javascript" src="http://static.blog.csdn.net/scripts/comment.js"></script>
    <div id="ad_bot">
    </div>
    <script type="text/javascript">
    new Ad(5, 'ad_bot');
    </script>
<div id="report_dialog">
</div>
<div id="d-top" style="display: none;">
    <a id="d-top-a" href="#" title="回到顶部" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_huidaodingbu'])">
        <img src="http://static.blog.csdn.net/images/top.png" alt="TOP" /></a>
</div>
<script type="text/javascript">
    $(function ()
    {
        var d_top = $('#d-top');
        document.onscroll = function ()
        {
            var scrTop = (document.body.scrollTop || document.documentElement.scrollTop);
            if (scrTop > 500)
            {
                d_top.show();
            } else
            {
                d_top.hide();
            }
        }
        $('#d-top-a').click(function ()
        {
            scrollTo(0, 0);
            this.blur();
            return false;
        });
    });
  
</script>
<style type="text/css">
    .tag_list
    {
        background: none repeat scroll 0 0 #FFFFFF;
        border: 1px solid #D7CBC1;
        color: #000000;
        font-size: 12px;
        line-height: 20px;
        list-style: none outside none;
        margin: 10px 2% 0 1%;
        padding: 1px;
    }
    .tag_list h5
    {
        background: none repeat scroll 0 0 #E0DBD3;
        color: #47381C;
        font-size: 12px;
        height: 24px;
        line-height: 24px;
        padding: 0 5px;
        margin: 0;
    }
    .tag_list h5 a
    {
        color: #47381C;
    }
    .classify
    {
        margin: 10px 0;
        padding: 4px 12px 8px;
    }
    .classify a
    {
        margin-right: 20px;
        white-space: nowrap;
    }
</style>
<div class="tag_list">
    <h5>
        <a href="http://www.csdn.net/tag/" target="_blank">核心技术类目</a></h5>
    <div class="classify">
<a title="全部主题" href="http://www.csdn.net/tag" target="_blank" onclick="LogClickCount(this,336);">全部主题</a>
<a title="Java" href="http://www.csdn.net/tag/Java" target="_blank" onclick="LogClickCount(this,336);">Java</a>
<a title="VPN" href="http://www.csdn.net/tag/vpn" target="_blank" onclick="LogClickCount(this,336);">VPN</a>
<a title="Android" href="http://www.csdn.net/tag/android" target="_blank" onclick="LogClickCount(this,336);">Android</a>
<a title="iOS" href="http://www.csdn.net/tag/ios" target="_blank" onclick="LogClickCount(this,336);">iOS</a>
<a title="ERP" href="http://www.csdn.net/tag/erp" target="_blank" onclick="LogClickCount(this,336);">ERP</a>
<a title="IE10" href="http://www.csdn.net/tag/ie10" target="_blank" onclick="LogClickCount(this,336);">IE10</a>
<a title="Eclipse" href="http://www.csdn.net/tag/eclipse" target="_blank" onclick="LogClickCount(this,336);">Eclipse</a>
<a title="CRM" href="http://www.csdn.net/tag/crm" target="_blank" onclick="LogClickCount(this,336);">CRM</a>
<a title="JavaScript" href="http://www.csdn.net/tag/javascript" target="_blank" onclick="LogClickCount(this,336);">JavaScript</a>
<a title="Ubuntu" href="http://www.csdn.net/tag/ubuntu" target="_blank" onclick="LogClickCount(this,336);">Ubuntu</a>
<a title="NFC" href="http://www.csdn.net/tag/nfc" target="_blank" onclick="LogClickCount(this,336);">NFC</a>
<a title="WAP" href="http://www.csdn.net/tag/wap" target="_blank" onclick="LogClickCount(this,336);">WAP</a>
<a title="jQuery" href="http://www.csdn.net/tag/jquery" target="_blank" onclick="LogClickCount(this,336);">jQuery</a>
<a title="数据库" href="http://www.csdn.net/tag/数据库" target="_blank" onclick="LogClickCount(this,336);">数据库</a>
<a title="BI" href="http://www.csdn.net/tag/bi" target="_blank" onclick="LogClickCount(this,336);">BI</a>
<a title="HTML5" href="http://www.csdn.net/tag/html5" target="_blank" onclick="LogClickCount(this,336);">HTML5</a>
<a title="Spring" href="http://www.csdn.net/tag/spring" target="_blank" onclick="LogClickCount(this,336);">Spring</a>
<a title="Apache" href="http://www.csdn.net/tag/apache" target="_blank" onclick="LogClickCount(this,336);">Apache</a>
<a title="Hadoop" href="http://www.csdn.net/tag/hadoop" target="_blank" onclick="LogClickCount(this,336);">Hadoop</a>
<a title=".NET" href="http://www.csdn.net/tag/.net" target="_blank" onclick="LogClickCount(this,336);">.NET</a>
<a title="API" href="http://www.csdn.net/tag/api" target="_blank" onclick="LogClickCount(this,336);">API</a>
<a title="HTML" href="http://www.csdn.net/tag/html" target="_blank" onclick="LogClickCount(this,336);">HTML</a>
<a title="SDK" href="http://www.csdn.net/tag/sdk" target="_blank" onclick="LogClickCount(this,336);">SDK</a>
<a title="IIS" href="http://www.csdn.net/tag/iis" target="_blank" onclick="LogClickCount(this,336);">IIS</a>
<a title="Fedora" href="http://www.csdn.net/tag/fedora" target="_blank" onclick="LogClickCount(this,336);">Fedora</a>
<a title="XML" href="http://www.csdn.net/tag/xml" target="_blank" onclick="LogClickCount(this,336);">XML</a>
<a title="LBS" href="http://www.csdn.net/tag/lbs" target="_blank" onclick="LogClickCount(this,336);">LBS</a>
<a title="Unity" href="http://www.csdn.net/tag/unity" target="_blank" onclick="LogClickCount(this,336);">Unity</a>
<a title="Splashtop" href="http://www.csdn.net/tag/splashtop" target="_blank" onclick="LogClickCount(this,336);">Splashtop</a>
<a title="UML" href="http://www.csdn.net/tag/uml" target="_blank" onclick="LogClickCount(this,336);">UML</a>
<a title="components" href="http://www.csdn.net/tag/components" target="_blank" onclick="LogClickCount(this,336);">components</a>
<a title="Windows Mobile" href="http://www.csdn.net/tag/windowsmobile" target="_blank" onclick="LogClickCount(this,336);">Windows Mobile</a>
<a title="Rails" href="http://www.csdn.net/tag/rails" target="_blank" onclick="LogClickCount(this,336);">Rails</a>
<a title="QEMU" href="http://www.csdn.net/tag/qemu" target="_blank" onclick="LogClickCount(this,336);">QEMU</a>
<a title="KDE" href="http://www.csdn.net/tag/kde" target="_blank" onclick="LogClickCount(this,336);">KDE</a>
<a title="Cassandra" href="http://www.csdn.net/tag/cassandra" target="_blank" onclick="LogClickCount(this,336);">Cassandra</a>
<a title="CloudStack" href="http://www.csdn.net/tag/cloudstack" target="_blank" onclick="LogClickCount(this,336);">CloudStack</a>
<a title="FTC" href="http://www.csdn.net/tag/ftc" target="_blank" onclick="LogClickCount(this,336);">FTC</a>
<a title="coremail" href="http://www.csdn.net/tag/coremail" target="_blank" onclick="LogClickCount(this,336);">coremail</a>
<a title="OPhone " href="http://www.csdn.net/tag/ophone " target="_blank" onclick="LogClickCount(this,336);">OPhone </a>
<a title="CouchBase" href="http://www.csdn.net/tag/couchbase" target="_blank" onclick="LogClickCount(this,336);">CouchBase</a>
<a title="云计算" href="http://www.csdn.net/tag/云计算" target="_blank" onclick="LogClickCount(this,336);">云计算</a>
<a title="iOS6" href="http://www.csdn.net/tag/iOS6" target="_blank" onclick="LogClickCount(this,336);">iOS6</a>
<a title="Rackspace " href="http://www.csdn.net/tag/rackspace " target="_blank" onclick="LogClickCount(this,336);">Rackspace </a>
<a title="Web App" href="http://www.csdn.net/tag/webapp" target="_blank" onclick="LogClickCount(this,336);">Web App</a>
<a title="SpringSide" href="http://www.csdn.net/tag/springside" target="_blank" onclick="LogClickCount(this,336);">SpringSide</a>
<a title="Maemo" href="http://www.csdn.net/tag/maemo" target="_blank" onclick="LogClickCount(this,336);">Maemo</a>
<a title="Compuware" href="http://www.csdn.net/tag/compuware" target="_blank" onclick="LogClickCount(this,336);">Compuware</a>
<a title="大数据" href="http://www.csdn.net/tag/大数据" target="_blank" onclick="LogClickCount(this,336);">大数据</a>
<a title="aptech" href="http://www.csdn.net/tag/aptech" target="_blank" onclick="LogClickCount(this,336);">aptech</a>
<a title="Perl" href="http://www.csdn.net/tag/perl" target="_blank" onclick="LogClickCount(this,336);">Perl</a>
<a title="Tornado" href="http://www.csdn.net/tag/tornado" target="_blank" onclick="LogClickCount(this,336);">Tornado</a>
<a title="Ruby" href="http://www.csdn.net/tag/ruby" target="_blank" onclick="LogClickCount(this,336);">Ruby</a>
<a title="Hibernate" href="http://www.csdn.net/hibernate" target="_blank" onclick="LogClickCount(this,336);">Hibernate</a>
<a title="ThinkPHP" href="http://www.csdn.net/tag/thinkphp" target="_blank" onclick="LogClickCount(this,336);">ThinkPHP</a>
<a title="Spark" href="http://www.csdn.net/tag/spark" target="_blank" onclick="LogClickCount(this,336);">Spark</a>
<a title="HBase" href="http://www.csdn.net/tag/hbase" target="_blank" onclick="LogClickCount(this,336);">HBase</a>
<a title="Pure" href="http://www.csdn.net/tag/pure" target="_blank" onclick="LogClickCount(this,336);">Pure</a>
<a title="Solr" href="http://www.csdn.net/tag/solr" target="_blank" onclick="LogClickCount(this,336);">Solr</a>
<a title="Angular" href="http://www.csdn.net/tag/angular" target="_blank" onclick="LogClickCount(this,336);">Angular</a>
<a title="Cloud Foundry" href="http://www.csdn.net/tag/cloudfoundry" target="_blank" onclick="LogClickCount(this,336);">Cloud Foundry</a>
<a title="Redis" href="http://www.csdn.net/tag/redis" target="_blank" onclick="LogClickCount(this,336);">Redis</a>
<a title="Scala" href="http://www.csdn.net/tag/scala" target="_blank" onclick="LogClickCount(this,336);">Scala</a>
<a title="Django" href="http://www.csdn.net/tag/django" target="_blank" onclick="LogClickCount(this,336);">Django</a>
<a title="Bootstrap" href="http://www.csdn.net/tag/bootstrap" target="_blank" onclick="LogClickCount(this,336);">Bootstrap</a>
    </div>
</div>

                    <div class="clear">
                    </div>
                </div>
            </div>
            <div id="side">
    <div class="side">
<div id="panel_Profile" class="panel">
<ul class="panel_head"><span>个人资料</span></ul>
<ul class="panel_body profile">
<div id="blog_userface">
    <a href="http://my.csdn.net/Luoshengyang" target="_blank">
    <img src="http://avatar.csdn.net/5/6/E/1_luoshengyang.jpg" title="访问我的空间" style="max-width:90%"/>
    </a>
    <br />
    <span><a href="http://my.csdn.net/Luoshengyang" class="user_name" target="_blank">Luoshengyang</a></span>
</div>
<div class="interact">
<a href="javascript:void(0);" class="attent" id="span_add_follow" title="[加关注]" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_guanzhu'])"></a>
<a href="javascript:void(0);" class="letter" onclick="loginto(1)" title="[发私信]" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_sixin'])"></a>
</div>
<div id="blog_medal">
        <div class="ico_expert" title="CSDN认证专家"></div>
</div>
<ul id="blog_rank">
    <li>访问：<span>3165201次</span></li>
    <li>积分：<span>16463分</span></li>
    <li>排名：<span>第128名</span></li>
</ul>
<ul id="blog_statistics">
    <li>原创：<span>100篇</span></li>
    <li>转载：<span>0篇</span></li>
    <li>译文：<span>0篇</span></li>
    <li>评论：<span>5216条</span></li>
</ul>
</ul>
</div>


<div id="custom_column_6567056" class="panel">
<ul class="panel_head"><span>博客公告</span></ul>
<ul class="panel_body">
<b><font color="red" size="2">本博客所有文章均为原创，欢迎交流，欢迎转载；转载请勿篡改内容，并且注明出处，禁止用于商业目的，谢谢！</font></b>
</ul>
</div><div id="custom_column_21664874" class="panel">
<ul class="panel_head"><span>图书信息</span></ul>
<ul class="panel_body">
<font color="red"><b>书名：</b></font>
<p>《Android系统源代码情景分析》</p>

<p><a href="http://wenku.it168.com/d_000574719.shtml" target="_blank">试读请点击</a></p>

<p><font color="red"><b>出版社：</b></font></p>
<p>电子工业出版社</p>

<p><font color="red"><b>网店：</b></font></p>

<p>1. <a href="http://product.dangdang.com/product.aspx?product_id=22884086" target="_blank">当当网（满100减20，满200减50）</a></p><p></p>

<p>2. <a href="http://book.360buy.com/11104739.html" target="_blank">京东网（满99减20）</a></p><p></p>

<p>3. <a href="http://www.amazon.cn/Android%E7%B3%BB%E7%BB%9F%E6%BA%90%E4%BB%A3%E7%A0%81%E6%83%85%E6%99%AF%E5%88%86%E6%9E%90-%E7%BD%97%E5%8D%87%E9%98%B3/dp/B009OLU8EE" target="_blank">亚马逊网（满100减20，满200减50）</a></p><p></p>

<p>4. <a href="http://product.china-pub.com/3684413" target="_blank">互动出版网</a></p><p></p>

<p>5. <a href="http://www.suning.com/emall/prd_10052_22001_-7_3435777_.html" target="_blank">苏宁易购网</a></p><p></p>

<p><a href="http://s.etao.com/search?spm=1002.8.1.1386.g76Rk3&amp;q=Android%CF%B5%CD%B3%D4%B4%B4%FA%C2%EB%C7%E9%BE%B0%B7%D6%CE%F6&amp;style=list&amp;initiative_id=etao_20121011&amp;pn=1&amp;sort=sale-desc" target="_blank">比一比谁更实惠</a></p>

<p><font color="red"><b>号外：</b></font></p>

<p>本书繁体版已经成功输出到台湾</p>

<p></p>
</ul>
</div><div id="custom_column_21603386" class="panel">
<ul class="panel_head"><span>联系方式</span></ul>
<ul class="panel_body">
<font color="red"><b>新浪微博：</b></font>
<p><a href="http://weibo.com/shengyangluo" target="_blank"><font color="red"><b>http://weibo.com/shengyangluo</b></font></a></p><p></p>

<font color="red"><b>QQ交流群：</b></font>
<p><b><font color="red">130112760</font></b>（1000人群，已满）</p>
<p><b><font color="red">248749286</font></b>（1000人群，已满）</p>
<p><b><font color="red">204155322</font></b>（500人群，未满）</p>
<p><b><font color="red">278558417</font></b>（500人群，已满）</p>
<p><b><font color="red">303165655</font></b>（500人群，已满）</p>
<p>PS：请勿同时加入多个群，一经发现，永久封号，谢谢！</p>
</ul>
</div><div id="panel_Category" class="panel">
    <ul class="panel_head"><span>博客专栏</span></ul>
    <ul class="panel_body" id="sp_column">
    <table cellpadding="0" cellspacing="0"><tr>
    <td style="padding:10px 10px 0 0;">
    <a href="http://blog.csdn.net/column/details/androidluo.html" target="_blank"><img src="http://avatar.csdn.net/blogpic/20111107095438958.jpg" style="width:75px;height:75px;" /></a>
    </td>
    <td style="padding:10px 0; vertical-align:top;">
    <a href="http://blog.csdn.net/column/details/androidluo.html" target="_blank">老罗的Android之旅</a>
    <p>文章：100篇</p>
    <span>阅读：3169042</span>
    </td>
    </tr></table>
    </ul>
</div><div id="hotarticls" class="panel">
<ul class="panel_head"><span>阅读排行</span></ul>
<ul class="panel_body itemlist">
<li>
<a href="/luoshengyang/article/details/6559955" title="在Ubuntu上下载、编译和安装Android最新源代码">在Ubuntu上下载、编译和安装Android最新源代码</a><span>(109478)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6618363" title="Android进程间通信（IPC）机制Binder简要介绍和学习计划">Android进程间通信（IPC）机制Binder简要介绍和学习计划</a><span>(95385)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6689748" title="Android应用程序启动过程源代码分析">Android应用程序启动过程源代码分析</a><span>(80910)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6568411" title="在Ubuntu上为Android系统编写Linux内核驱动程序">在Ubuntu上为Android系统编写Linux内核驱动程序</a><span>(78655)</span>
</li>
<li>
<a href="/luoshengyang/article/details/8923485" title="那两年炼就的Android内功修养">那两年炼就的Android内功修养</a><span>(76761)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6567257" title="Android硬件抽象层（HAL）概要介绍和学习计划">Android硬件抽象层（HAL）概要介绍和学习计划</a><span>(72556)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6564592" title="在Ubuntu上下载、编译和安装Android最新内核源代码（Linux Kernel）">在Ubuntu上下载、编译和安装Android最新内核源代码（Linux Kernel）</a><span>(66727)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6557518" title="Android学习启动篇">Android学习启动篇</a><span>(59079)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6566662" title="如何单独编译Android源代码中的模块">如何单独编译Android源代码中的模块</a><span>(58027)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6575988" title="在Ubuntu为Android硬件抽象层（HAL）模块编写JNI方法提供Java访问硬件服务接口">在Ubuntu为Android硬件抽象层（HAL）模块编写JNI方法提供Java访问硬件服务接口</a><span>(56751)</span>
</li>
</ul>
</div>
<div id="hotarticls2" class="panel">
<ul class="panel_head"><span>评论排行</span></ul>
<ul class="panel_body itemlist">
<li>
<a href="/luoshengyang/article/details/6689748" title="Android应用程序启动过程源代码分析">Android应用程序启动过程源代码分析</a><span>(322)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6559955" title="在Ubuntu上下载、编译和安装Android最新源代码">在Ubuntu上下载、编译和安装Android最新源代码</a><span>(238)</span>
</li>
<li>
<a href="/luoshengyang/article/details/8116866" title="《Android系统源代码情景分析》一书勘误">《Android系统源代码情景分析》一书勘误</a><span>(208)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6882903" title="Android应用程序键盘（Keyboard）消息处理机制分析">Android应用程序键盘（Keyboard）消息处理机制分析</a><span>(182)</span>
</li>
<li>
<a href="/luoshengyang/article/details/8923485" title="那两年炼就的Android内功修养">那两年炼就的Android内功修养</a><span>(182)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6580267" title="在Ubuntu上为Android系统内置Java应用程序测试Application Frameworks层的硬件服务">在Ubuntu上为Android系统内置Java应用程序测试Application Frameworks层的硬件服务</a><span>(170)</span>
</li>
<li>
<a href="/luoshengyang/article/details/7409491" title="Android博客文章整理">Android博客文章整理</a><span>(167)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6568411" title="在Ubuntu上为Android系统编写Linux内核驱动程序">在Ubuntu上为Android系统编写Linux内核驱动程序</a><span>(151)</span>
</li>
<li>
<a href="/luoshengyang/article/details/8452527" title="2012年的Android之旅：梦想、学习、坚持、自信、淡定">2012年的Android之旅：梦想、学习、坚持、自信、淡定</a><span>(139)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6564592" title="在Ubuntu上下载、编译和安装Android最新内核源代码（Linux Kernel）">在Ubuntu上下载、编译和安装Android最新内核源代码（Linux Kernel）</a><span>(136)</span>
</li>
</ul>
</div>
<div id="newcomments" class="panel">
<ul class="panel_head"><span>最新评论</span></ul>
<ul class="panel_body itemlist">
    <li>
    <a href="/Luoshengyang/article/details/8923485#comments">那两年炼就的Android内功修养</a>
    <p style="margin:0px;"><a href="/h137286510" class="user_name">h137286510</a>:
我是搞底层显示驱动的，最近想研究下surface，就百度下跑你这来了。看完你写的surface系列，...
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/6786239#comments">Android系统的智能指针（轻量级指针、强指针和弱指针）的实现原理分析</a>
    <p style="margin:0px;"><a href="/ssikyou" class="user_name">ssikyou</a>:
顶老罗！补充，多调用的addWeakRef在4.4里已经没有了，OBJECT_LIFETIME_FO...
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/6817933#comments">Android应用程序消息处理机制（Looper、Handler）分析</a>
    <p style="margin:0px;"><a href="/yuanshisenlin123" class="user_name">yuanshisenlin123</a>:
做了将近两年的Android应用开发，表示没看懂，看来还得多多学习哇！
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/19023609#comments">Android源代码编译命令m/mm/mmm/make分析</a>
    <p style="margin:0px;"><a href="/thinkinwm" class="user_name">thinkinwm</a>:
好文章！
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/6568411#comments">在Ubuntu上为Android系统编写Linux内核驱动程序</a>
    <p style="margin:0px;"><a href="/HuiyuYang_fish" class="user_name">HuiyuYang_fish</a>:
期待实验~
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/6557518#comments">Android学习启动篇</a>
    <p style="margin:0px;"><a href="/HuiyuYang_fish" class="user_name">HuiyuYang_fish</a>:
貌似我也要开始android的初步涉猎了~
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/12957169#comments">《老罗的Android之旅》导读PPT</a>
    <p style="margin:0px;"><a href="/mianju23" class="user_name">mianju23</a>:
牛人
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/8452527#comments">2012年的Android之旅：梦想、学习、坚持、自信、淡定</a>
    <p style="margin:0px;"><a href="/wuxiaoming1733" class="user_name">wuxiaoming1733</a>:
顶楼主
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/6737352#comments">Android应用程序注册广播接收器（registerReceiver）的过程分析</a>
    <p style="margin:0px;"><a href="/wuxiaoming1733" class="user_name">wuxiaoming1733</a>:
罗大神你好，我这边还没明白，怎么自己用代码，实现androidmanifest.xml里静态注册系统...
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/6642463#comments">Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析</a>
    <p style="margin:0px;"><a href="/zqz19891031" class="user_name">zqz19891031</a>:
博主您好，看了你的博客，收获颇多！有一个问题想请教：最近在看Android的Binder实现，看到B...
    </p>
    </li>
</ul>
</div>
    </div>
    <div class="clear">
    </div>
</div>

            <div class="clear">
            </div>
        </div>
        

<script type="text/javascript" src="http://static.blog.csdn.net/scripts/newblog.min.js"></script>
<script type="text/javascript" src="http://medal.blog.csdn.net/showblogmedal.ashx?blogid=1134701"></script>
<script type="text/javascript">
    document.write('<script type="text/javascript" src="http://csdnimg.cn/pubfooter/js/publib_footer.js?' + Math.floor(new Date() / 120000).toString(36) + '="></' + 'script>');
</script>
    <script type="text/javascript" src="http://passport.csdn.net/content/loginbox/login.js"></script>
<script type="text/javascript">document.write("<img src=http://counter.csdn.net/pv.aspx?id=24 border=0 width=0 height=0>");</script>
<script type="text/javascript" src="http://www.csdn.net/ui/scripts/Csdn/counter.js"></script>
<script type="text/javascript" src="http://ad.csdn.net/scripts/ad-blog.js"></script>
<script type="text/javascript" src="http://zz.csdn.net/js/count.js"></script>
<script type="text/javascript">
    $(function () {
        function __get_code_toolbar(snippet_id) {
            return $("<a href='https://code.csdn.net/snippets/"
                    + snippet_id
                    + "' target='_blank' title='在CODE上查看代码片' style='text-indent:0;'><img src='https://code.csdn.net/assets/CODE_ico.png' width=12 height=12 alt='在CODE上查看代码片' style='position:relative;top:1px;left:2px;'/></a>"
                    + "<a href='https://code.csdn.net/snippets/"
                    + snippet_id
                    + "/fork' target='_blank' title='派生到我的代码片'  style='text-indent:0;'><img src='https://code.csdn.net/assets/ico_fork.svg' width=12 height=12 alt='派生到我的代码片' style='position:relative;top:2px;left:2px;'/></a>");
        }
        
        $("[code_snippet_id]").each(function () {
            __s_id = $(this).attr("code_snippet_id");
            if (__s_id != null && __s_id != "" && __s_id != 0 && parseInt(__s_id) > 70020) {
                __code_tool = __get_code_toolbar(__s_id);
                $(this).prev().find(".tools").append(__code_tool);
            }
        });
    });
</script>

    </div>
      <!--new top-->
    
    <script id="csdn-toolbar-id" btnId="header_notice_num" wrapId="note1" count="5" subCount="5" type="text/javascript" src="http://static.csdn.net/public/common/toolbar/js/toolbar.js"></script>     <!--new top-->
</body>
</html>
